Libraries

library(tidyverse)
library(lubridate)
library(stringr)
library(ggplot2)
library(ggridges)
library(htmltools)
library(bslib)
library(plotly)
library(dplyr)
library(grDevices)
library(usmap)
library(kableExtra)

library(showtext)     # <-- ADD
showtext_auto()       # <-- ADD
font_add_google("Playfair Display", "playfair")   # <-- ADD
shopping <- read_csv("proper_raw_shopping_behavior.csv")
shopping

Summary

This project explores shopping behavior using a dataset from Kaggle, containing data from 3,900 U.S. shoppers. The analysis focused on spending patterns, demographic trends, and seasonal or regional differences in purchasing habits. The goal was to identify which groups shop the most, which categories draw the highest spending, and how patterns shift or differ based on location and time of year.

After exploratory data analysis was performed, clear trends appeared such as mid-range spending, consistent seasonal fluctuations, and noticeable imbalances in gender representation. The results offer a broad picture of who shops, what they prefer, and where the most activity occurs, creating a foundation for understanding customer behavior in a simplified retail environment.

Purpose

The goal of this project was to explore how demographic and seasonal factors influence shopping behavior. The main questions to be answered were: Who spends the most? Which products and colors are most popular? How do location and season affect purchase trends? This analysis helps show how businesses might better understand consumer preferences and plan marketing strategies.

Data

  1. Dataset Description & Features

The dataset came from Kaggle and contains 3,900 U.S.-based customer records with 18 total attributes describing shopping patterns, preferences, and demographics. This project focused on 10 of those variables to highlight specific spending and behavioral trends rather than analyzing every available feature.

The variables used were:

variables <- data.frame(
  Variable = c("Gender", "Age", "Category", "Color", "Purchase_Amount_(USD)",
               "Payment_Method", "Location", "Season"),
  Type = c("Categorical", "Numeric", "Categorical", "Categorical", "Numeric",
           "Categorical", "Categorical", "Categorical"),
  Description_Unit = c(
    "Male or Female",
    "Age of customer in years",
    "Product category (ex: Clothing, Footwear, etc.)",
    "Product color purchased",
    "Purchase amount in U.S. dollars",
    "Method used for payment (Debit/Credit Card, PayPal, etc.)",
    "Customer’s U.S. state",
    "Season of purchase (Spring, Summer, Fall, Winter)"
  )
)

kable(variables, col.names = c("Variable", "Type", "Description / Unit")) %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover")) %>%
  row_spec(0, bold = TRUE, color = "#fff", background = "#cc0099")
Variable Type Description / Unit
Gender Categorical Male or Female
Age Numeric Age of customer in years
Category Categorical Product category (ex: Clothing, Footwear, etc.)
Color Categorical Product color purchased
Purchase_Amount_(USD) Numeric Purchase amount in U.S. dollars
Payment_Method Categorical Method used for payment (Debit/Credit Card, PayPal, etc.)
Location Categorical Customer’s U.S. state
Season Categorical Season of purchase (Spring, Summer, Fall, Winter)

These variables provided a good balance between numeric and categorical data that helped explore spending behavior, preferences, and demographic patterns.

  1. Missing & Null Values There were no major missing or null values in the dataset. The data was already clean, with complete entries for all selected columns. Since the dataset was in good shape, there was no need to make any corrections or fill in missing values before analysis. This made it easier to jump straight into exploring patterns and building visuals.

  2. Methodology and Changes The dataset was already in a tidy format, each row clearly represented a single purchase record and each column represented a single attribute. tidyverse and dplyr libraries were used for summarizing, filtering, and visualizing data. Functions like count(), mutate(), and summarize() were also used to help create comparisons between gender, categories, and locations.

When visualizing, the reorder() function was used with ggplot2 to organize bars and boxplots in a more readable way. Other than that, the dataset didn’t require any major structural changes, so the main focus was on exploring relationships and identifying trends in spending and shopping behavior.

Exploratory Data Analysis

a) Summary Stats & Overview

summary(shopping)
  Customer ID          Age           Gender          Item_Purchased       Category        
 Min.   :   1.0   Min.   :18.00   Length:3900        Length:3900        Length:3900       
 1st Qu.: 975.8   1st Qu.:31.00   Class :character   Class :character   Class :character  
 Median :1950.5   Median :44.00   Mode  :character   Mode  :character   Mode  :character  
 Mean   :1950.5   Mean   :44.07                                                           
 3rd Qu.:2925.2   3rd Qu.:57.00                                                           
 Max.   :3900.0   Max.   :70.00                                                           
 Purchase_Amount_(USD)   Location             Size              Color          
 Min.   : 20.00        Length:3900        Length:3900        Length:3900       
 1st Qu.: 39.00        Class :character   Class :character   Class :character  
 Median : 60.00        Mode  :character   Mode  :character   Mode  :character  
 Mean   : 59.76                                                                
 3rd Qu.: 81.00                                                                
 Max.   :100.00                                                                
    Season          Review_Rating  Subscription_Status Shipping_Type     
 Length:3900        Min.   :2.50   Length:3900         Length:3900       
 Class :character   1st Qu.:3.10   Class :character    Class :character  
 Mode  :character   Median :3.70   Mode  :character    Mode  :character  
                    Mean   :3.75                                         
                    3rd Qu.:4.40                                         
                    Max.   :5.00                                         
 Discount_Applied   Promo_Code_Used    Previous_Purchases Payment_Method    
 Length:3900        Length:3900        Min.   : 1.00      Length:3900       
 Class :character   Class :character   1st Qu.:13.00      Class :character  
 Mode  :character   Mode  :character   Median :25.00      Mode  :character  
                                       Mean   :25.35                        
                                       3rd Qu.:38.00                        
                                       Max.   :50.00                        
 Frequency of Purchases
 Length:3900           
 Class :character      
 Mode  :character      
                       
                       
                       
  • The summary statistics gives a quick view of the dataset’s structure. Customer ages range from 18 to 70, with a median of 44, showing that the data is frequently around middle-aged shoppers. Purchase amounts range from 20 dollars to 100, with a median of 60 dollars and a mean of about $59.8, which supports the idea that most spending falls in a steady mid-range instead of at the extreme ends. Previous purchases show a wide distribution (1 to 50), suggesting customers vary a lot in how frequently they shop. There is a mix of categorical and numerical variables. Overall, the summary shows that the dataset is complete (no missing values shown), balanced, and structured in a way that supports a straightforward analysis.

Histogram for Age distribution 👶 👴

ggplot(shopping, aes(x = Age)) + 
  geom_histogram(binwidth = 5, fill = "maroon3", color = "thistle1") + 
  labs(
    title = "Distribution of Customer Ages", 
    x = "Age", 
    y = "Count"
  ) +  
  theme(
    text = element_text(family = "playfair"),
    plot.title = element_text(family = "playfair", face = "bold", size = 16),
    plot.subtitle = element_text(family = "playfair", size = 11),
    axis.title = element_text(family = "playfair", size = 12),
    axis.text = element_text(family = "playfair", size = 10),
    panel.grid.minor = element_blank()
  )

  • This histogram shows the distribution of the ages of the customers from the dataset. It can be seen that there are roughly two peaks, the first around 20-30 and the second between 50 and 60. This suggests that the main groups of shoppers are either young or old. There are fewer middle-aged shoppers in this population.

Histogram for purchase amount distribution 🛒💲

ggplot(shopping, aes(x = `Purchase_Amount_(USD)` )) + 
  geom_histogram(binwidth = 5,  fill = "maroon3", color = "thistle1") + 
  labs(
    title = "Distribution of Purchase Amounts", 
    x = "Purchase Amount in Dollars", 
    y = "Number of Purchases"
  ) +  
  theme(
    text = element_text(family = "playfair"),
    plot.title = element_text(family = "playfair", face = "bold", size = 16),
    plot.subtitle = element_text(family = "playfair", size = 11),
    axis.title = element_text(family = "playfair", size = 12),
    axis.text = element_text(family = "playfair", size = 10),
    panel.grid.minor = element_blank()
  )

  • This bar chart shows the distribution of purchase amounts from the shopping data. There’s two or three peaks, one around the 30–35 dollar range and another near 90–95 dollars. This means that customers tend to spend either on the lower or higher end, with fewer purchases falling in the mid-range.

Box Plot for Purchase Amount by Product Category

shopping %>%
  ggplot(aes(x = reorder(Category, `Purchase_Amount_(USD)`, median), 
             y = `Purchase_Amount_(USD)`, fill = Category)) +
  geom_boxplot(show.legend = FALSE, alpha = 0.6) +
  coord_flip() +
  labs(
    title = "Purchase Amount by Product Category",
    subtitle = "Outerwear and Clothing show slightly higher spending ranges.",
    x = "Product Category",
    y = "Purchase Amount in Dollars"
  ) + 
  theme(
    text = element_text(family = "playfair"),
    plot.title = element_text(family = "playfair", face = "bold", size = 16),
    plot.subtitle = element_text(family = "playfair", size = 11),
    axis.title = element_text(family = "playfair", size = 12),
    axis.text = element_text(family = "playfair", size = 10),
    panel.grid.minor = element_blank()
  )

  • This boxplot shows how spending looks across the main product categories and helps analyze which areas customers spend their money on the most. Footwear, Clothing, and Accessories all have similar median purchase amounts, but their spreads are different, which means some categories have more variation in what people are willing to spend. Outerwear has the widest spread, suggesting customers either buy very low-cost basics or pricier pieces depending on the style or season. This visual helps support the overall goal of the project by showing which categories have the most consistent spending and where customers tend to shop across a wider price range.

Average Spending by Gender

shopping %>%
  group_by(Gender) %>%
  summarize(
    avg_spending = mean(`Purchase_Amount_(USD)`, na.rm = TRUE),
    total_spending = sum(`Purchase_Amount_(USD)`)
  )

shopping %>%
  group_by(Gender) %>%
  summarize(avg_spending = mean(`Purchase_Amount_(USD)`, na.rm = TRUE)) %>%
  ggplot(aes(x = Gender, y = avg_spending, fill = Gender)) +
  geom_col(alpha = 0.8) +
  scale_fill_manual(values = c("Female" = "#cc0099", "Male" = "lightblue")) +
  labs(
    title = "Average Spending by Gender",
    subtitle = "Shows the mean purchase amount across all transactions.",
    x = "Gender",
    y = "Average Spending (USD)"
  ) +
  theme(
    text = element_text(family = "playfair"),
    plot.title = element_text(family = "playfair", face = "bold", size = 16),
    plot.subtitle = element_text(family = "playfair", size = 11),
    axis.title = element_text(family = "playfair", size = 12),
    axis.text = element_text(family = "playfair", size = 10),
    legend.position = "none"
  )

  • Even though male customers made more total purchases, their higher totals are mostly due to how heavily the dataset is skewed toward men. When comparing averages instead of totals, female shoppers actually spent slightly more per purchase. This contrast shows exactly how important it is to look at both totals and averages together, since totals reflect sample size while averages reflect behavior. So even though men appear to spend more overall, women are actually just as active (or even a bit more generous) on a per-purchase basis.

Total Spending by Gender

shopping %>%
  group_by(Gender) %>%
  summarize(total_spending = sum(`Purchase_Amount_(USD)`, na.rm = TRUE)) %>%
  ggplot(aes(x = Gender, y = total_spending, fill = Gender)) +
  geom_col(alpha = 0.8) +
  scale_fill_manual(values = c("Female" = "#cc0099", "Male" = "lightblue")) +
  labs(
    title = "Total Spending by Gender",
    subtitle = "Shows the combined purchase amount across all customers.",
    x = "Gender",
    y = "Total Spending (USD)"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    text = element_text(family = "playfair"),
    plot.title = element_text(family = "playfair", face = "bold", size = 16),
    plot.subtitle = element_text(family = "playfair", size = 11),
    axis.title = element_text(family = "playfair", size = 12),
    axis.text = element_text(family = "playfair", size = 10),
    legend.position = "none"
  )

  • This chart compares the total amount spent by male and female customers. Male shoppers clearly lead in total spending, but that’s mostly because there are more of them in the dataset. Even though men made more purchases overall, it doesn’t necessarily mean they spend more per purchase, just that their larger numbers add up to a higher total.

c) Product & Color Preferences

Product Category by Gender

shopping %>%
  count(Gender, Category) %>%
  ggplot(aes(x = Category, y = n, fill = Gender)) +
  geom_col(position = "dodge", alpha = 0.7) +
  scale_fill_manual(values = c("Female" = "#cc0099", "Male" = "lightblue")) +
  labs(title = "Product Categories by Gender",
       x = "Category", y = "Number of Purchases") + 
  theme(
    text = element_text(family = "playfair"),
    plot.title = element_text(family = "playfair", face = "bold", size = 16),
    plot.subtitle = element_text(family = "playfair", size = 11),
    axis.title = element_text(family = "playfair", size = 12),
    axis.text = element_text(family = "playfair", size = 10),
    panel.grid.minor = element_blank()
  )

  • This chart compares product category purchases by gender. It is clear that the sample does not reflect the population. Clothing and accessories are the most popular across both groups, but males consistently make more purchases overall in every category. The gap is very noticeable in all categories, but especially clothing and footwear. This reflects the dataset’s imbalance, since it contains more male entries – meaning the results noticeably show shopping behavior within this sample rather than representing the broader population.

Top 5 Colors by Gender

color_by_gender <- shopping %>%
  count(Gender, Color, name = "Occurrences") %>%
  group_by(Gender) %>%
  slice_max(order_by = Occurrences, n = 5)

ggplot(color_by_gender, aes(x = reorder(Color, Occurrences),
                            y = Occurrences, fill = Gender)) +
  geom_col(position = "identity", alpha = 0.7) + #this position = "identity" part was so helpful, before the graph was so weird and the sizes of the bars were very off, but this fixed it so that they would just overlap. The problem was that the bars were trying to stay the same size even though they were overlapping.
  scale_fill_manual(values = c("Female" = "#cc0099", "Male" = "lightblue")) +
  labs(
    title = "Top 5 Colors by Gender",
    subtitle = "Transparent overlap highlights shared color preferences.",
    x = "Color",
    y = "Number of Purchases"
  ) +
 theme_minimal(base_size = 12) +
  theme(
    text = element_text(family = "playfair"),
    plot.title = element_text(family = "playfair", face = "bold", size = 16),
    plot.subtitle = element_text(family = "playfair", size = 11),
    axis.title = element_text(family = "playfair", size = 12),
    axis.text = element_text(family = "playfair", size = 10),
    legend.text = element_text(family = "playfair", size = 10),
    legend.title = element_text(family = "playfair", face = "bold", size = 11),
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "top"
  )

  • This chart compares the top color choices between male and female shoppers. Pink, magenta, and green are most popular among women, while men lean toward cooler tones like teal, cyan, and silver. You’d usually expect more overlap between the groups, but since this dataset has more male entries overall and came significantly tidy, it likely skews the color rankings. Even with that imbalance, yellow and olive still show up as shared favorites across both groups, which might represent more neutral or universally appealing tones.

Top 5 Colors by Product Category

top_colors_by_cat <- shopping %>%
  count(Category, Color, name = "Occurances") %>%
  group_by(Category) %>%
  slice_max(order_by = Occurances, n=5)

top_colors_by_cat %>%
  ggplot(aes(x = reorder(Color, Occurances), 
             y = Occurances, 
             fill = Category)) +
  geom_col(show.legend = FALSE, color = "thistle1", alpha = 0.8) +
  coord_flip() +
  facet_wrap(~ Category, scales = "free_y") +
  labs(
    title = "Top 5 Colors by Product Category",
    subtitle = "Most frequently purchased colors within each category.",
    x = "Color",
    y = "Number of Occurrences"
  ) +
  scale_fill_manual(values = rep("#cc0099", length(unique(top_colors_by_cat$Category)))) + 
  theme(
    text = element_text(family = "playfair"),
    plot.title = element_text(family = "playfair", face = "bold", size = 16),
    plot.subtitle = element_text(family = "playfair", size = 11),
    axis.title = element_text(family = "playfair", size = 12),
    axis.text = element_text(family = "playfair", size = 10),
    panel.grid.minor = element_blank()
  )

  • This chart shows the five most frequently purchased colors within each product category. Accessories lean toward neutral and earthy tones like Olive and Gray, while Clothing includes deeper shades like Teal and Maroon. Footwear trends toward softer colors, and Outerwear favors cooler ones such as Blue and Violet.

Results

Conclusions

References

LS0tCnRpdGxlOiAiRGVsaXZlcmFibGUgNSIKYXV0aG9yOiAi772h4ouGy5rirZHin6HinLTvuI4gS2VsYnkgTUsgUGFsbWVyIOKctO+4juKfoeKtkcua4ouG772hIgpkYXRlOiAiTm92ZW1iZXIgOSwgMjAyNSIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIHRoZW1lOiAKICAgICAgdmVyc2lvbjogNAogICAgICBiZzogIiNmZmU2ZmYiCiAgICAgIGZnOiAiI2NjMDA5OSIKICAgICAgcHJpbWFyeTogIiM2YjJiMWEiCiAgICAgIGJhc2VfZm9udDogCiAgICAgICAgZ29vZ2xlOiAiU291cmNlIFNhbnMgUHJvIgogICAgICBoZWFkaW5nX2ZvbnQ6IAogICAgICAgIGdvb2dsZTogIlBsYXlmYWlyIERpc3BsYXkiCi0tLQoKCiMgTGlicmFyaWVzCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdncmlkZ2VzKQpsaWJyYXJ5KGh0bWx0b29scykKbGlicmFyeShic2xpYikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ3JEZXZpY2VzKQpsaWJyYXJ5KHVzbWFwKQpsaWJyYXJ5KGthYmxlRXh0cmEpCgpsaWJyYXJ5KHNob3d0ZXh0KSAgICAgIyA8LS0gQURECnNob3d0ZXh0X2F1dG8oKSAgICAgICAjIDwtLSBBREQKZm9udF9hZGRfZ29vZ2xlKCJQbGF5ZmFpciBEaXNwbGF5IiwgInBsYXlmYWlyIikgICAjIDwtLSBBREQKCgpgYGAKCmBgYHtyfQpzaG9wcGluZyA8LSByZWFkX2NzdigicHJvcGVyX3Jhd19zaG9wcGluZ19iZWhhdmlvci5jc3YiKQpzaG9wcGluZwpgYGAKCgojIFN1bW1hcnkKVGhpcyBwcm9qZWN0IGV4cGxvcmVzIHNob3BwaW5nIGJlaGF2aW9yIHVzaW5nIGEgZGF0YXNldCBmcm9tIEthZ2dsZSwgY29udGFpbmluZyBkYXRhIGZyb20gMyw5MDAgVS5TLiBzaG9wcGVycy4gVGhlIGFuYWx5c2lzIGZvY3VzZWQgb24gc3BlbmRpbmcgcGF0dGVybnMsIGRlbW9ncmFwaGljIHRyZW5kcywgYW5kIHNlYXNvbmFsIG9yIHJlZ2lvbmFsIGRpZmZlcmVuY2VzIGluIHB1cmNoYXNpbmcgaGFiaXRzLiBUaGUgZ29hbCB3YXMgdG8gaWRlbnRpZnkgd2hpY2ggZ3JvdXBzIHNob3AgdGhlIG1vc3QsIHdoaWNoIGNhdGVnb3JpZXMgZHJhdyB0aGUgaGlnaGVzdCBzcGVuZGluZywgYW5kIGhvdyBwYXR0ZXJucyBzaGlmdCBvciBkaWZmZXIgYmFzZWQgb24gbG9jYXRpb24gYW5kIHRpbWUgb2YgeWVhci4KCkFmdGVyIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgd2FzIHBlcmZvcm1lZCwgY2xlYXIgdHJlbmRzIGFwcGVhcmVkIHN1Y2ggYXMgbWlkLXJhbmdlIHNwZW5kaW5nLCBjb25zaXN0ZW50IHNlYXNvbmFsIGZsdWN0dWF0aW9ucywgYW5kIG5vdGljZWFibGUgaW1iYWxhbmNlcyBpbiBnZW5kZXIgcmVwcmVzZW50YXRpb24uIFRoZSByZXN1bHRzIG9mZmVyIGEgYnJvYWQgcGljdHVyZSBvZiB3aG8gc2hvcHMsIHdoYXQgdGhleSBwcmVmZXIsIGFuZCB3aGVyZSB0aGUgbW9zdCBhY3Rpdml0eSBvY2N1cnMsIGNyZWF0aW5nIGEgZm91bmRhdGlvbiBmb3IgdW5kZXJzdGFuZGluZyBjdXN0b21lciBiZWhhdmlvciBpbiBhIHNpbXBsaWZpZWQgcmV0YWlsIGVudmlyb25tZW50LgoKCiMgUHVycG9zZQpUaGUgZ29hbCBvZiB0aGlzIHByb2plY3Qgd2FzIHRvIGV4cGxvcmUgaG93IGRlbW9ncmFwaGljIGFuZCBzZWFzb25hbCBmYWN0b3JzIGluZmx1ZW5jZSBzaG9wcGluZyBiZWhhdmlvci4gVGhlIG1haW4gcXVlc3Rpb25zIHRvIGJlIGFuc3dlcmVkIHdlcmU6IFdobyBzcGVuZHMgdGhlIG1vc3Q/IFdoaWNoIHByb2R1Y3RzIGFuZCBjb2xvcnMgYXJlIG1vc3QgcG9wdWxhcj8gSG93IGRvIGxvY2F0aW9uIGFuZCBzZWFzb24gYWZmZWN0IHB1cmNoYXNlIHRyZW5kcz8gVGhpcyBhbmFseXNpcyBoZWxwcyBzaG93IGhvdyBidXNpbmVzc2VzIG1pZ2h0IGJldHRlciB1bmRlcnN0YW5kIGNvbnN1bWVyIHByZWZlcmVuY2VzIGFuZCBwbGFuIG1hcmtldGluZyBzdHJhdGVnaWVzLgoKIyBEYXRhCgphLiBEYXRhc2V0IERlc2NyaXB0aW9uICYgRmVhdHVyZXMKClRoZSBkYXRhc2V0IGNhbWUgZnJvbSBLYWdnbGUgYW5kIGNvbnRhaW5zIDMsOTAwIFUuUy4tYmFzZWQgY3VzdG9tZXIgcmVjb3JkcyB3aXRoIDE4IHRvdGFsIGF0dHJpYnV0ZXMgZGVzY3JpYmluZyBzaG9wcGluZyBwYXR0ZXJucywgcHJlZmVyZW5jZXMsIGFuZCBkZW1vZ3JhcGhpY3MuIFRoaXMgcHJvamVjdCBmb2N1c2VkIG9uIDEwIG9mIHRob3NlIHZhcmlhYmxlcyB0byBoaWdobGlnaHQgc3BlY2lmaWMgc3BlbmRpbmcgYW5kIGJlaGF2aW9yYWwgdHJlbmRzIHJhdGhlciB0aGFuIGFuYWx5emluZyBldmVyeSBhdmFpbGFibGUgZmVhdHVyZS4KClRoZSB2YXJpYWJsZXMgdXNlZCB3ZXJlOgpgYGB7cn0KdmFyaWFibGVzIDwtIGRhdGEuZnJhbWUoCiAgVmFyaWFibGUgPSBjKCJHZW5kZXIiLCAiQWdlIiwgIkNhdGVnb3J5IiwgIkNvbG9yIiwgIlB1cmNoYXNlX0Ftb3VudF8oVVNEKSIsCiAgICAgICAgICAgICAgICJQYXltZW50X01ldGhvZCIsICJMb2NhdGlvbiIsICJTZWFzb24iKSwKICBUeXBlID0gYygiQ2F0ZWdvcmljYWwiLCAiTnVtZXJpYyIsICJDYXRlZ29yaWNhbCIsICJDYXRlZ29yaWNhbCIsICJOdW1lcmljIiwKICAgICAgICAgICAiQ2F0ZWdvcmljYWwiLCAiQ2F0ZWdvcmljYWwiLCAiQ2F0ZWdvcmljYWwiKSwKICBEZXNjcmlwdGlvbl9Vbml0ID0gYygKICAgICJNYWxlIG9yIEZlbWFsZSIsCiAgICAiQWdlIG9mIGN1c3RvbWVyIGluIHllYXJzIiwKICAgICJQcm9kdWN0IGNhdGVnb3J5IChleDogQ2xvdGhpbmcsIEZvb3R3ZWFyLCBldGMuKSIsCiAgICAiUHJvZHVjdCBjb2xvciBwdXJjaGFzZWQiLAogICAgIlB1cmNoYXNlIGFtb3VudCBpbiBVLlMuIGRvbGxhcnMiLAogICAgIk1ldGhvZCB1c2VkIGZvciBwYXltZW50IChEZWJpdC9DcmVkaXQgQ2FyZCwgUGF5UGFsLCBldGMuKSIsCiAgICAiQ3VzdG9tZXLigJlzIFUuUy4gc3RhdGUiLAogICAgIlNlYXNvbiBvZiBwdXJjaGFzZSAoU3ByaW5nLCBTdW1tZXIsIEZhbGwsIFdpbnRlcikiCiAgKQopCgprYWJsZSh2YXJpYWJsZXMsIGNvbC5uYW1lcyA9IGMoIlZhcmlhYmxlIiwgIlR5cGUiLCAiRGVzY3JpcHRpb24gLyBVbml0IikpICU+JQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSkgJT4lCiAgcm93X3NwZWMoMCwgYm9sZCA9IFRSVUUsIGNvbG9yID0gIiNmZmYiLCBiYWNrZ3JvdW5kID0gIiNjYzAwOTkiKQpgYGAKCgpUaGVzZSB2YXJpYWJsZXMgcHJvdmlkZWQgYSBnb29kIGJhbGFuY2UgYmV0d2VlbiBudW1lcmljIGFuZCBjYXRlZ29yaWNhbCBkYXRhIHRoYXQgaGVscGVkIGV4cGxvcmUgc3BlbmRpbmcgYmVoYXZpb3IsIHByZWZlcmVuY2VzLCBhbmQgZGVtb2dyYXBoaWMgcGF0dGVybnMuCgpiLiBNaXNzaW5nICYgTnVsbCBWYWx1ZXMKVGhlcmUgd2VyZSBubyBtYWpvciBtaXNzaW5nIG9yIG51bGwgdmFsdWVzIGluIHRoZSBkYXRhc2V0LiBUaGUgZGF0YSB3YXMgYWxyZWFkeSBjbGVhbiwgd2l0aCBjb21wbGV0ZSBlbnRyaWVzIGZvciBhbGwgc2VsZWN0ZWQgY29sdW1ucy4gU2luY2UgdGhlIGRhdGFzZXQgd2FzIGluIGdvb2Qgc2hhcGUsIHRoZXJlIHdhcyBubyBuZWVkIHRvIG1ha2UgYW55IGNvcnJlY3Rpb25zIG9yIGZpbGwgaW4gbWlzc2luZyB2YWx1ZXMgYmVmb3JlIGFuYWx5c2lzLiBUaGlzIG1hZGUgaXQgZWFzaWVyIHRvIGp1bXAgc3RyYWlnaHQgaW50byBleHBsb3JpbmcgcGF0dGVybnMgYW5kIGJ1aWxkaW5nIHZpc3VhbHMuCgpjLiBNZXRob2RvbG9neSBhbmQgQ2hhbmdlcwpUaGUgZGF0YXNldCB3YXMgYWxyZWFkeSBpbiBhIHRpZHkgZm9ybWF0LCBlYWNoIHJvdyBjbGVhcmx5IHJlcHJlc2VudGVkIGEgc2luZ2xlIHB1cmNoYXNlIHJlY29yZCBhbmQgZWFjaCBjb2x1bW4gcmVwcmVzZW50ZWQgYSBzaW5nbGUgYXR0cmlidXRlLiB0aWR5dmVyc2UgYW5kIGRwbHlyIGxpYnJhcmllcyB3ZXJlIHVzZWQgZm9yIHN1bW1hcml6aW5nLCBmaWx0ZXJpbmcsIGFuZCB2aXN1YWxpemluZyBkYXRhLiBGdW5jdGlvbnMgbGlrZSBjb3VudCgpLCBtdXRhdGUoKSwgYW5kIHN1bW1hcml6ZSgpIHdlcmUgYWxzbyB1c2VkIHRvIGhlbHAgY3JlYXRlIGNvbXBhcmlzb25zIGJldHdlZW4gZ2VuZGVyLCBjYXRlZ29yaWVzLCBhbmQgbG9jYXRpb25zLgoKV2hlbiB2aXN1YWxpemluZywgdGhlIHJlb3JkZXIoKSBmdW5jdGlvbiB3YXMgdXNlZCB3aXRoIGdncGxvdDIgdG8gb3JnYW5pemUgYmFycyBhbmQgYm94cGxvdHMgaW4gYSBtb3JlIHJlYWRhYmxlIHdheS4gT3RoZXIgdGhhbiB0aGF0LCB0aGUgZGF0YXNldCBkaWRu4oCZdCByZXF1aXJlIGFueSBtYWpvciBzdHJ1Y3R1cmFsIGNoYW5nZXMsIHNvIHRoZSBtYWluIGZvY3VzIHdhcyBvbiBleHBsb3JpbmcgcmVsYXRpb25zaGlwcyBhbmQgaWRlbnRpZnlpbmcgdHJlbmRzIGluIHNwZW5kaW5nIGFuZCBzaG9wcGluZyBiZWhhdmlvci4KCiMgKipFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzKioKCiMjIGEpIFN1bW1hcnkgU3RhdHMgJiBPdmVydmlldwoKYGBge3J9CnN1bW1hcnkoc2hvcHBpbmcpCmBgYAotIFRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MgZ2l2ZXMgYSBxdWljayB2aWV3IG9mIHRoZSBkYXRhc2V0J3Mgc3RydWN0dXJlLiBDdXN0b21lciBhZ2VzIHJhbmdlIGZyb20gMTggdG8gNzAsIHdpdGggYSBtZWRpYW4gb2YgNDQsIHNob3dpbmcgdGhhdCB0aGUgZGF0YSBpcyBmcmVxdWVudGx5IGFyb3VuZCBtaWRkbGUtYWdlZCBzaG9wcGVycy4gUHVyY2hhc2UgYW1vdW50cyByYW5nZSBmcm9tIDIwIGRvbGxhcnMgdG8gMTAwLCB3aXRoIGEgbWVkaWFuIG9mIDYwIGRvbGxhcnMgYW5kIGEgbWVhbiBvZiBhYm91dCAkNTkuOCwgd2hpY2ggc3VwcG9ydHMgdGhlIGlkZWEgdGhhdCBtb3N0IHNwZW5kaW5nIGZhbGxzIGluIGEgc3RlYWR5IG1pZC1yYW5nZSBpbnN0ZWFkIG9mIGF0IHRoZSBleHRyZW1lIGVuZHMuIFByZXZpb3VzIHB1cmNoYXNlcyBzaG93IGEgd2lkZSBkaXN0cmlidXRpb24gKDEgdG8gNTApLCBzdWdnZXN0aW5nIGN1c3RvbWVycyB2YXJ5IGEgbG90IGluIGhvdyBmcmVxdWVudGx5IHRoZXkgc2hvcC4gVGhlcmUgaXMgYSBtaXggb2YgY2F0ZWdvcmljYWwgYW5kIG51bWVyaWNhbCB2YXJpYWJsZXMuIE92ZXJhbGwsIHRoZSBzdW1tYXJ5IHNob3dzIHRoYXQgdGhlIGRhdGFzZXQgaXMgY29tcGxldGUgKG5vIG1pc3NpbmcgdmFsdWVzIHNob3duKSwgYmFsYW5jZWQsIGFuZCBzdHJ1Y3R1cmVkIGluIGEgd2F5IHRoYXQgc3VwcG9ydHMgYSBzdHJhaWdodGZvcndhcmQgYW5hbHlzaXMuCgoKIyMjICoqSGlzdG9ncmFtKiogZm9yIF9BZ2UgZGlzdHJpYnV0aW9uXyDwn5G2IPCfkbQgCmBgYHtyfQpnZ3Bsb3Qoc2hvcHBpbmcsIGFlcyh4ID0gQWdlKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGZpbGwgPSAibWFyb29uMyIsIGNvbG9yID0gInRoaXN0bGUxIikgKyAKICBsYWJzKAogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEN1c3RvbWVyIEFnZXMiLCAKICAgIHggPSAiQWdlIiwgCiAgICB5ID0gIkNvdW50IgogICkgKyAgCiAgdGhlbWUoCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBmYWNlID0gImJvbGQiLCBzaXplID0gMTYpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMCksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpCiAgKQpgYGAKLSBUaGlzIGhpc3RvZ3JhbSBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBhZ2VzIG9mIHRoZSBjdXN0b21lcnMgZnJvbSB0aGUgZGF0YXNldC4gSXQgY2FuIGJlIHNlZW4gdGhhdCB0aGVyZSBhcmUgcm91Z2hseSB0d28gcGVha3MsIHRoZSBmaXJzdCBhcm91bmQgMjAtMzAgYW5kIHRoZSBzZWNvbmQgYmV0d2VlbiA1MCBhbmQgNjAuIFRoaXMgc3VnZ2VzdHMgdGhhdCB0aGUgbWFpbiBncm91cHMgb2Ygc2hvcHBlcnMgYXJlIGVpdGhlciB5b3VuZyBvciBvbGQuIFRoZXJlIGFyZSBmZXdlciBtaWRkbGUtYWdlZCBzaG9wcGVycyBpbiB0aGlzIHBvcHVsYXRpb24uCgojIyMgKipIaXN0b2dyYW0qKiBmb3IgX3B1cmNoYXNlIGFtb3VudCBkaXN0cmlidXRpb25fIPCfm5Lwn5KyCmBgYHtyfQpnZ3Bsb3Qoc2hvcHBpbmcsIGFlcyh4ID0gYFB1cmNoYXNlX0Ftb3VudF8oVVNEKWAgKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsICBmaWxsID0gIm1hcm9vbjMiLCBjb2xvciA9ICJ0aGlzdGxlMSIpICsgCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBQdXJjaGFzZSBBbW91bnRzIiwgCiAgICB4ID0gIlB1cmNoYXNlIEFtb3VudCBpbiBEb2xsYXJzIiwgCiAgICB5ID0gIk51bWJlciBvZiBQdXJjaGFzZXMiCiAgKSArICAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEwKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAotIFRoaXMgYmFyIGNoYXJ0IHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgcHVyY2hhc2UgYW1vdW50cyBmcm9tIHRoZSBzaG9wcGluZyBkYXRhLiBUaGVyZSdzIHR3byBvciB0aHJlZSBwZWFrcywgb25lIGFyb3VuZCB0aGUgMzDigJMzNSBkb2xsYXIgcmFuZ2UgYW5kIGFub3RoZXIgbmVhciA5MOKAkzk1IGRvbGxhcnMuIFRoaXMgbWVhbnMgdGhhdCBjdXN0b21lcnMgdGVuZCB0byBzcGVuZCBlaXRoZXIgb24gdGhlIGxvd2VyIG9yIGhpZ2hlciBlbmQsIHdpdGggZmV3ZXIgcHVyY2hhc2VzIGZhbGxpbmcgaW4gdGhlIG1pZC1yYW5nZS4KCiMjIyAqKkJveCBQbG90KiogZm9yIF9QdXJjaGFzZSBBbW91bnQgYnkgUHJvZHVjdCBDYXRlZ29yeV8gCgpgYGB7cn0Kc2hvcHBpbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihDYXRlZ29yeSwgYFB1cmNoYXNlX0Ftb3VudF8oVVNEKWAsIG1lZGlhbiksIAogICAgICAgICAgICAgeSA9IGBQdXJjaGFzZV9BbW91bnRfKFVTRClgLCBmaWxsID0gQ2F0ZWdvcnkpKSArCiAgZ2VvbV9ib3hwbG90KHNob3cubGVnZW5kID0gRkFMU0UsIGFscGhhID0gMC42KSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiUHVyY2hhc2UgQW1vdW50IGJ5IFByb2R1Y3QgQ2F0ZWdvcnkiLAogICAgc3VidGl0bGUgPSAiT3V0ZXJ3ZWFyIGFuZCBDbG90aGluZyBzaG93IHNsaWdodGx5IGhpZ2hlciBzcGVuZGluZyByYW5nZXMuIiwKICAgIHggPSAiUHJvZHVjdCBDYXRlZ29yeSIsCiAgICB5ID0gIlB1cmNoYXNlIEFtb3VudCBpbiBEb2xsYXJzIgogICkgKyAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEwKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAotIFRoaXMgYm94cGxvdCBzaG93cyBob3cgc3BlbmRpbmcgbG9va3MgYWNyb3NzIHRoZSBtYWluIHByb2R1Y3QgY2F0ZWdvcmllcyBhbmQgaGVscHMgYW5hbHl6ZSB3aGljaCBhcmVhcyBjdXN0b21lcnMgc3BlbmQgdGhlaXIgbW9uZXkgb24gdGhlIG1vc3QuIEZvb3R3ZWFyLCBDbG90aGluZywgYW5kIEFjY2Vzc29yaWVzIGFsbCBoYXZlIHNpbWlsYXIgbWVkaWFuIHB1cmNoYXNlIGFtb3VudHMsIGJ1dCB0aGVpciBzcHJlYWRzIGFyZSBkaWZmZXJlbnQsIHdoaWNoIG1lYW5zIHNvbWUgY2F0ZWdvcmllcyBoYXZlIG1vcmUgdmFyaWF0aW9uIGluIHdoYXQgcGVvcGxlIGFyZSB3aWxsaW5nIHRvIHNwZW5kLiBPdXRlcndlYXIgaGFzIHRoZSB3aWRlc3Qgc3ByZWFkLCBzdWdnZXN0aW5nIGN1c3RvbWVycyBlaXRoZXIgYnV5IHZlcnkgbG93LWNvc3QgYmFzaWNzIG9yIHByaWNpZXIgcGllY2VzIGRlcGVuZGluZyBvbiB0aGUgc3R5bGUgb3Igc2Vhc29uLiBUaGlzIHZpc3VhbCBoZWxwcyBzdXBwb3J0IHRoZSBvdmVyYWxsIGdvYWwgb2YgdGhlIHByb2plY3QgYnkgc2hvd2luZyB3aGljaCBjYXRlZ29yaWVzIGhhdmUgdGhlIG1vc3QgY29uc2lzdGVudCBzcGVuZGluZyBhbmQgd2hlcmUgY3VzdG9tZXJzIHRlbmQgdG8gc2hvcCBhY3Jvc3MgYSB3aWRlciBwcmljZSByYW5nZS4KCgojIyBiKSBTaG9wcGluZyBCZWhhdmlvciAmIFNwZW5kaW5nIFRyZW5kcwoKIyMjIFBheW1lbnQgTWV0aG9kcyBEaXN0cmlidXRpb24gICDwn5KzIPCfkrUg8J+TsQpgYGB7cn0Kc2hvcHBpbmcgJT4lCiAgY291bnQoUGF5bWVudF9NZXRob2QpICU+JQogIG11dGF0ZShwY3QgPSBuIC8gc3VtKG4pKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKFBheW1lbnRfTWV0aG9kLCBwY3QpLCB5ID0gcGN0LCBmaWxsID0gUGF5bWVudF9NZXRob2QpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzY2FsZXM6OnBlcmNlbnQocGN0LCBhY2N1cmFjeSA9IDAuMSkpLCB2anVzdCA9IC0wLjMpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFBheW1lbnQgTWV0aG9kcyIsCiAgICBzdWJ0aXRsZSA9ICJNYWpvcml0eSBvZiBwdXJjaGFzZXMgd2VyZSBtYWRlIHZpYSBDcmVkaXQgQ2FyZCBhbmQgUGF5UGFsLiIsCiAgICB4ID0gIlBheW1lbnQgTWV0aG9kIiwKICAgIHkgPSAiU2hhcmUgb2YgVG90YWwgVHJhbnNhY3Rpb25zIgogICkgKwogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDExKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTApLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKYGBgCi0gVGhpcyBiYXIgY2hhcnQgc2hvd3MgdGhhdCBDcmVkaXQgQ2FyZCBhbmQgUGF5UGFsIGFyZSB0aGUgbW9zdCBjb21tb24gcGF5bWVudCBtZXRob2RzLiBCYW5rIFRyYW5zZmVyIGlzIHVzZWQgdGhlIGxlYXN0LCBsaWtlbHkgZHVlIHRvIGl0cyBzbG93ZXIgcHJvY2Vzc2luZyBhbmQgdGhlIGxhY2sgb2YgcmV3YXJkcywgYXMgY29tcGFyZWQgdG8gY3JlZGl0IGNhcmRzLiBCYW5rIHRyYW5zZmVycyBhbHNvIHRlbmQgdG8gaW52b2x2ZSBtb3JlIHN0ZXBzIGFuZCBzZWN1cml0eSBtZWFzdXJlcyB0aGFuIGRpZ2l0YWwgcGF5bWVudHMsIHNvIGl0IG1ha2VzIHNlbnNlIHRoYXQgc2hvcHBlcnMgcHJlZmVyIGZhc3Rlciwgb25lLWNsaWNrIG9wdGlvbnMgbGlrZSBQYXlQYWwgYW5kIGNyZWRpdCBjYXJkcy4KCiMjIEF2ZXJhZ2UgU3BlbmRpbmcgYnkgR2VuZGVyCmBgYHtyfQpzaG9wcGluZyAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHN1bW1hcml6ZSgKICAgIGF2Z19zcGVuZGluZyA9IG1lYW4oYFB1cmNoYXNlX0Ftb3VudF8oVVNEKWAsIG5hLnJtID0gVFJVRSksCiAgICB0b3RhbF9zcGVuZGluZyA9IHN1bShgUHVyY2hhc2VfQW1vdW50XyhVU0QpYCkKICApCgpzaG9wcGluZyAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHN1bW1hcml6ZShhdmdfc3BlbmRpbmcgPSBtZWFuKGBQdXJjaGFzZV9BbW91bnRfKFVTRClgLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIsIHkgPSBhdmdfc3BlbmRpbmcsIGZpbGwgPSBHZW5kZXIpKSArCiAgZ2VvbV9jb2woYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJGZW1hbGUiID0gIiNjYzAwOTkiLCAiTWFsZSIgPSAibGlnaHRibHVlIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiQXZlcmFnZSBTcGVuZGluZyBieSBHZW5kZXIiLAogICAgc3VidGl0bGUgPSAiU2hvd3MgdGhlIG1lYW4gcHVyY2hhc2UgYW1vdW50IGFjcm9zcyBhbGwgdHJhbnNhY3Rpb25zLiIsCiAgICB4ID0gIkdlbmRlciIsCiAgICB5ID0gIkF2ZXJhZ2UgU3BlbmRpbmcgKFVTRCkiCiAgKSArCiAgdGhlbWUoCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBmYWNlID0gImJvbGQiLCBzaXplID0gMTYpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICApCgpgYGAKLSBFdmVuIHRob3VnaCBtYWxlIGN1c3RvbWVycyBtYWRlIG1vcmUgdG90YWwgcHVyY2hhc2VzLCB0aGVpciBoaWdoZXIgdG90YWxzIGFyZSBtb3N0bHkgZHVlIHRvIGhvdyBoZWF2aWx5IHRoZSBkYXRhc2V0IGlzIHNrZXdlZCB0b3dhcmQgbWVuLiBXaGVuIGNvbXBhcmluZyBhdmVyYWdlcyBpbnN0ZWFkIG9mIHRvdGFscywgZmVtYWxlIHNob3BwZXJzIGFjdHVhbGx5IHNwZW50IHNsaWdodGx5IG1vcmUgcGVyIHB1cmNoYXNlLiBUaGlzIGNvbnRyYXN0IHNob3dzIGV4YWN0bHkgaG93IGltcG9ydGFudCBpdCBpcyB0byBsb29rIGF0IGJvdGggdG90YWxzIGFuZCBhdmVyYWdlcyB0b2dldGhlciwgc2luY2UgdG90YWxzIHJlZmxlY3Qgc2FtcGxlIHNpemUgd2hpbGUgYXZlcmFnZXMgcmVmbGVjdCBiZWhhdmlvci4gU28gZXZlbiB0aG91Z2ggbWVuIGFwcGVhciB0byBzcGVuZCBtb3JlIG92ZXJhbGwsIHdvbWVuIGFyZSBhY3R1YWxseSBqdXN0IGFzIGFjdGl2ZSAob3IgZXZlbiBhIGJpdCBtb3JlIGdlbmVyb3VzKSBvbiBhIHBlci1wdXJjaGFzZSBiYXNpcy4KCgojIyMgVG90YWwgU3BlbmRpbmcgYnkgR2VuZGVyCmBgYHtyfQpzaG9wcGluZyAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9zcGVuZGluZyA9IHN1bShgUHVyY2hhc2VfQW1vdW50XyhVU0QpYCwgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gR2VuZGVyLCB5ID0gdG90YWxfc3BlbmRpbmcsIGZpbGwgPSBHZW5kZXIpKSArCiAgZ2VvbV9jb2woYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJGZW1hbGUiID0gIiNjYzAwOTkiLCAiTWFsZSIgPSAibGlnaHRibHVlIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiVG90YWwgU3BlbmRpbmcgYnkgR2VuZGVyIiwKICAgIHN1YnRpdGxlID0gIlNob3dzIHRoZSBjb21iaW5lZCBwdXJjaGFzZSBhbW91bnQgYWNyb3NzIGFsbCBjdXN0b21lcnMuIiwKICAgIHggPSAiR2VuZGVyIiwKICAgIHkgPSAiVG90YWwgU3BlbmRpbmcgKFVTRCkiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKwogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDExKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTApLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiCiAgKQpgYGAKLSBUaGlzIGNoYXJ0IGNvbXBhcmVzIHRoZSB0b3RhbCBhbW91bnQgc3BlbnQgYnkgbWFsZSBhbmQgZmVtYWxlIGN1c3RvbWVycy4gTWFsZSBzaG9wcGVycyBjbGVhcmx5IGxlYWQgaW4gdG90YWwgc3BlbmRpbmcsIGJ1dCB0aGF04oCZcyBtb3N0bHkgYmVjYXVzZSB0aGVyZSBhcmUgbW9yZSBvZiB0aGVtIGluIHRoZSBkYXRhc2V0LiBFdmVuIHRob3VnaCBtZW4gbWFkZSBtb3JlIHB1cmNoYXNlcyBvdmVyYWxsLCBpdCBkb2VzbuKAmXQgbmVjZXNzYXJpbHkgbWVhbiB0aGV5IHNwZW5kIG1vcmUgcGVyIHB1cmNoYXNlLCBqdXN0IHRoYXQgdGhlaXIgbGFyZ2VyIG51bWJlcnMgYWRkIHVwIHRvIGEgaGlnaGVyIHRvdGFsLgoKCiMjIGMpIFByb2R1Y3QgJiBDb2xvciBQcmVmZXJlbmNlcwoKIyMjIFByb2R1Y3QgQ2F0ZWdvcnkgYnkgR2VuZGVyCmBgYHtyfQpzaG9wcGluZyAlPiUKICBjb3VudChHZW5kZXIsIENhdGVnb3J5KSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBDYXRlZ29yeSwgeSA9IG4sIGZpbGwgPSBHZW5kZXIpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiLCBhbHBoYSA9IDAuNykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkZlbWFsZSIgPSAiI2NjMDA5OSIsICJNYWxlIiA9ICJsaWdodGJsdWUiKSkgKwogIGxhYnModGl0bGUgPSAiUHJvZHVjdCBDYXRlZ29yaWVzIGJ5IEdlbmRlciIsCiAgICAgICB4ID0gIkNhdGVnb3J5IiwgeSA9ICJOdW1iZXIgb2YgUHVyY2hhc2VzIikgKyAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEwKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAotIFRoaXMgY2hhcnQgY29tcGFyZXMgcHJvZHVjdCBjYXRlZ29yeSBwdXJjaGFzZXMgYnkgZ2VuZGVyLiBJdCBpcyBjbGVhciB0aGF0ICoqdGhlIHNhbXBsZSBkb2VzIG5vdCByZWZsZWN0IHRoZSBwb3B1bGF0aW9uLioqIENsb3RoaW5nIGFuZCBhY2Nlc3NvcmllcyBhcmUgdGhlIG1vc3QgcG9wdWxhciBhY3Jvc3MgYm90aCBncm91cHMsIGJ1dCBtYWxlcyBjb25zaXN0ZW50bHkgbWFrZSBtb3JlIHB1cmNoYXNlcyBvdmVyYWxsIGluIGV2ZXJ5IGNhdGVnb3J5LiBUaGUgZ2FwIGlzIHZlcnkgbm90aWNlYWJsZSBpbiBhbGwgY2F0ZWdvcmllcywgYnV0IGVzcGVjaWFsbHkgY2xvdGhpbmcgYW5kIGZvb3R3ZWFyLiBUaGlzIHJlZmxlY3RzIHRoZSBkYXRhc2V04oCZcyBpbWJhbGFuY2UsIHNpbmNlIGl0IGNvbnRhaW5zIG1vcmUgbWFsZSBlbnRyaWVzIC0tIG1lYW5pbmcgdGhlIHJlc3VsdHMgbm90aWNlYWJseSBzaG93IHNob3BwaW5nIGJlaGF2aW9yIHdpdGhpbiB0aGlzIHNhbXBsZSByYXRoZXIgdGhhbiByZXByZXNlbnRpbmcgdGhlIGJyb2FkZXIgcG9wdWxhdGlvbi4KCgojIyMgVG9wIDUgQ29sb3JzIGJ5IEdlbmRlcgpgYGB7cn0KY29sb3JfYnlfZ2VuZGVyIDwtIHNob3BwaW5nICU+JQogIGNvdW50KEdlbmRlciwgQ29sb3IsIG5hbWUgPSAiT2NjdXJyZW5jZXMiKSAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHNsaWNlX21heChvcmRlcl9ieSA9IE9jY3VycmVuY2VzLCBuID0gNSkKCmdncGxvdChjb2xvcl9ieV9nZW5kZXIsIGFlcyh4ID0gcmVvcmRlcihDb2xvciwgT2NjdXJyZW5jZXMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IE9jY3VycmVuY2VzLCBmaWxsID0gR2VuZGVyKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImlkZW50aXR5IiwgYWxwaGEgPSAwLjcpICsgI3RoaXMgcG9zaXRpb24gPSAiaWRlbnRpdHkiIHBhcnQgd2FzIHNvIGhlbHBmdWwsIGJlZm9yZSB0aGUgZ3JhcGggd2FzIHNvIHdlaXJkIGFuZCB0aGUgc2l6ZXMgb2YgdGhlIGJhcnMgd2VyZSB2ZXJ5IG9mZiwgYnV0IHRoaXMgZml4ZWQgaXQgc28gdGhhdCB0aGV5IHdvdWxkIGp1c3Qgb3ZlcmxhcC4gVGhlIHByb2JsZW0gd2FzIHRoYXQgdGhlIGJhcnMgd2VyZSB0cnlpbmcgdG8gc3RheSB0aGUgc2FtZSBzaXplIGV2ZW4gdGhvdWdoIHRoZXkgd2VyZSBvdmVybGFwcGluZy4KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJGZW1hbGUiID0gIiNjYzAwOTkiLCAiTWFsZSIgPSAibGlnaHRibHVlIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiVG9wIDUgQ29sb3JzIGJ5IEdlbmRlciIsCiAgICBzdWJ0aXRsZSA9ICJUcmFuc3BhcmVudCBvdmVybGFwIGhpZ2hsaWdodHMgc2hhcmVkIGNvbG9yIHByZWZlcmVuY2VzLiIsCiAgICB4ID0gIkNvbG9yIiwKICAgIHkgPSAiTnVtYmVyIG9mIFB1cmNoYXNlcyIKICApICsKIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpICsKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEwKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDExKSwKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIgogICkKYGBgCi0gVGhpcyBjaGFydCBjb21wYXJlcyB0aGUgdG9wIGNvbG9yIGNob2ljZXMgYmV0d2VlbiBtYWxlIGFuZCBmZW1hbGUgc2hvcHBlcnMuIFBpbmssIG1hZ2VudGEsIGFuZCBncmVlbiBhcmUgbW9zdCBwb3B1bGFyIGFtb25nIHdvbWVuLCB3aGlsZSBtZW4gbGVhbiB0b3dhcmQgY29vbGVyIHRvbmVzIGxpa2UgdGVhbCwgY3lhbiwgYW5kIHNpbHZlci4gWW914oCZZCB1c3VhbGx5IGV4cGVjdCBtb3JlIG92ZXJsYXAgYmV0d2VlbiB0aGUgZ3JvdXBzLCBidXQgc2luY2UgdGhpcyBkYXRhc2V0IGhhcyBtb3JlIG1hbGUgZW50cmllcyBvdmVyYWxsIGFuZCBjYW1lIHNpZ25pZmljYW50bHkgdGlkeSwgaXQgbGlrZWx5IHNrZXdzIHRoZSBjb2xvciByYW5raW5ncy4gRXZlbiB3aXRoIHRoYXQgaW1iYWxhbmNlLCB5ZWxsb3cgYW5kIG9saXZlIHN0aWxsIHNob3cgdXAgYXMgc2hhcmVkIGZhdm9yaXRlcyBhY3Jvc3MgYm90aCBncm91cHMsIHdoaWNoIG1pZ2h0IHJlcHJlc2VudCBtb3JlIG5ldXRyYWwgb3IgdW5pdmVyc2FsbHkgYXBwZWFsaW5nIHRvbmVzLgoKIyMjIFRvcCA1IENvbG9ycyBieSBQcm9kdWN0IENhdGVnb3J5CmBgYHtyfQp0b3BfY29sb3JzX2J5X2NhdCA8LSBzaG9wcGluZyAlPiUKICBjb3VudChDYXRlZ29yeSwgQ29sb3IsIG5hbWUgPSAiT2NjdXJhbmNlcyIpICU+JQogIGdyb3VwX2J5KENhdGVnb3J5KSAlPiUKICBzbGljZV9tYXgob3JkZXJfYnkgPSBPY2N1cmFuY2VzLCBuPTUpCgp0b3BfY29sb3JzX2J5X2NhdCAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKENvbG9yLCBPY2N1cmFuY2VzKSwgCiAgICAgICAgICAgICB5ID0gT2NjdXJhbmNlcywgCiAgICAgICAgICAgICBmaWxsID0gQ2F0ZWdvcnkpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSwgY29sb3IgPSAidGhpc3RsZTEiLCBhbHBoYSA9IDAuOCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgZmFjZXRfd3JhcCh+IENhdGVnb3J5LCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJUb3AgNSBDb2xvcnMgYnkgUHJvZHVjdCBDYXRlZ29yeSIsCiAgICBzdWJ0aXRsZSA9ICJNb3N0IGZyZXF1ZW50bHkgcHVyY2hhc2VkIGNvbG9ycyB3aXRoaW4gZWFjaCBjYXRlZ29yeS4iLAogICAgeCA9ICJDb2xvciIsCiAgICB5ID0gIk51bWJlciBvZiBPY2N1cnJlbmNlcyIKICApICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSByZXAoIiNjYzAwOTkiLCBsZW5ndGgodW5pcXVlKHRvcF9jb2xvcnNfYnlfY2F0JENhdGVnb3J5KSkpKSArIAogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDExKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTApLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCmBgYAotIFRoaXMgY2hhcnQgc2hvd3MgdGhlIGZpdmUgbW9zdCBmcmVxdWVudGx5IHB1cmNoYXNlZCBjb2xvcnMgd2l0aGluIGVhY2ggcHJvZHVjdCBjYXRlZ29yeS4gQWNjZXNzb3JpZXMgbGVhbiB0b3dhcmQgbmV1dHJhbCBhbmQgZWFydGh5IHRvbmVzIGxpa2UgT2xpdmUgYW5kIEdyYXksIHdoaWxlIENsb3RoaW5nIGluY2x1ZGVzIGRlZXBlciBzaGFkZXMgbGlrZSBUZWFsIGFuZCBNYXJvb24uIEZvb3R3ZWFyIHRyZW5kcyB0b3dhcmQgc29mdGVyIGNvbG9ycywgYW5kIE91dGVyd2VhciBmYXZvcnMgY29vbGVyIG9uZXMgc3VjaCBhcyBCbHVlIGFuZCBWaW9sZXQuCgojIyBkKSBSZWdpb25hbCAmIFNlYXNvbmFsIFRyZW5kcwoKIyMjIFRvcCAxMCBDdXN0b21lciBMb2NhdGlvbnMg8J+TjSDwn5e677iPCmBgYHtyfQpzaG9wcGluZyAlPiUKICBjb3VudChMb2NhdGlvbiwgbmFtZSA9ICJQdXJjaGFzZXMiKSAlPiUKICBhcnJhbmdlKGRlc2MoUHVyY2hhc2VzKSkgJT4lCiAgc2xpY2VfaGVhZChuID0gMTApICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoTG9jYXRpb24sIFB1cmNoYXNlcyksIHkgPSBQdXJjaGFzZXMpKSArCiAgZ2VvbV9jb2woZmlsbCA9ICIjY2MwMDk5IikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh0aXRsZSA9ICJUb3AgMTAgQ3VzdG9tZXIgTG9jYXRpb25zIGJ5IFB1cmNoYXNlIFZvbHVtZSIsCiAgICAgICB4ID0gIkxvY2F0aW9uIiwgeSA9ICJOdW1iZXIgb2YgUHVyY2hhc2VzIikgKyAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEwKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCmBgYAotIFRoaXMgYmFyIGNoYXJ0IHNob3dzIHdoZXJlIG1vc3QgY3VzdG9tZXJzIGFyZSBzaG9wcGluZyBmcm9tLiBNb250YW5hIGFuZCBDYWxpZm9ybmlhIGhhdmUgdGhlIG1vc3QgdG90YWwgcHVyY2hhc2VzLCB3aXRoIHN0YXRlcyBsaWtlIElkYWhvLCBJbGxpbm9pcywgYW5kIEFsYWJhbWEgY2xvc2UgYmVoaW5kLiBUaGUgZGlzdHJpYnV0aW9uIGxvb2tzIGZhaXJseSBiYWxhbmNlZCBvdmVyYWxsLCB3aXRoIG5vcm1hbCB2YXJpYW5jZSBiZXR3ZWVuIHN0YXRlcyB0aGF0IGNvdWxkIGJlIGJlY2F1c2Ugb2YgZGlmZmVyZW5jZXMgaW4gYW55dGhpbmcgZnJvbSBwb3B1bGF0aW9uIHRvIG1hcmtldGluZyBzdHJhdGVnaWVzIGluIGVhY2ggbG9jYXRpb24uCgojIyMgVS5TLiBNYXAgKFB1cmNoYXNlIFZvbHVtZSBieSBTdGF0ZSkKYGBge3J9CiMgdG8gbG9hZCB0aGUgZm9udApzaG93dGV4dF9hdXRvKCkKZm9udF9hZGRfZ29vZ2xlKCJQbGF5ZmFpciBEaXNwbGF5IiwgInBsYXlmYWlyIikKCiMgc3VtIHRoZSBzdGF0ZS1sZXZlbCBwdXJjaGFzZXMKc3RhdGVfcHVyY2hhc2VzIDwtIHNob3BwaW5nICU+JQogIGNvdW50KExvY2F0aW9uLCBuYW1lID0gIlB1cmNoYXNlcyIpICU+JQogIHJlbmFtZShzdGF0ZSA9IExvY2F0aW9uKSAlPiUKICBtdXRhdGUoY29kZSA9IHN0YXRlLmFiYlttYXRjaChzdGF0ZSwgc3RhdGUubmFtZSldKSAgIyBnZXQgc3RhdGUgYWJicmV2aWF0aW9ucwoKIyBtYWtlIGludGVyYWN0aXZlIG1hcAp1c19zaG9wcGluZ19tYXAgPC0gcGxvdF9nZW8oc3RhdGVfcHVyY2hhc2VzLCBsb2NhdGlvbm1vZGUgPSAiVVNBLXN0YXRlcyIpICU+JQogIGFkZF90cmFjZSgKICAgIGxvY2F0aW9ucyA9IH5jb2RlLAogICAgeiA9IH5QdXJjaGFzZXMsCiAgICB0ZXh0ID0gfnBhc3RlMCgKICAgICAgIjxiPiIsIHN0YXRlLCAiPC9iPjxicj4iLAogICAgICBQdXJjaGFzZXMsICIgcHVyY2hhc2VzIPCfm43vuI/inKjwn5KWIiAjdGhpcyBzaG91bGQgYmUgc2hvd24gb24gaG92ZXIKICAgICksCiAgICBob3ZlcmluZm8gPSAidGV4dCIsCiAgICBjb2xvcnNjYWxlID0gbGlzdChjKDAsIDEpLCBjKCIjZjhkNmUwIiwgIiNjYzAwOTkiKSksCiAgICBtYXJrZXIgPSBsaXN0KGxpbmUgPSBsaXN0KGNvbG9yID0gIndoaXRlIiwgd2lkdGggPSAxKSkKICApICU+JQogIGNvbG9yYmFyKHRpdGxlID0gIlB1cmNoYXNlcyIpICU+JQogIGxheW91dCgKICAgIHRpdGxlID0gbGlzdCgKICAgICAgdGV4dCA9ICI8Yj5DdXN0b21lciBQdXJjaGFzZSBWb2x1bWUgYnkgU3RhdGU8L2I+PGJyPjxzcGFuIHN0eWxlPSdmb250LXNpemU6MTJweDsnPkhvdmVyIHRvIGV4cGxvcmUgcmVnaW9uYWwgYWN0aXZpdHk8L3NwYW4+IiwKICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gIlBsYXlmYWlyIERpc3BsYXkiLCBzaXplID0gMjApCiAgICApLAogICAgZ2VvID0gbGlzdCgKICAgICAgc2NvcGUgPSAidXNhIiwKICAgICAgcHJvamVjdGlvbiA9IGxpc3QodHlwZSA9ICJhbGJlcnMgdXNhIiksCiAgICAgIGJnY29sb3IgPSAibGlnaHRibHVlIiwgICAgICAgICAgIyBiYWNrZ3JvdW5kCiAgICAgIGxha2Vjb2xvciA9ICIjZTlmMmY5IiwKICAgICAgc2hvd2xha2VzID0gVFJVRQogICAgKSwKICAgIGZvbnQgPSBsaXN0KGZhbWlseSA9ICJQbGF5ZmFpciBEaXNwbGF5IikKICApCgp1c19zaG9wcGluZ19tYXAKYGBgCi0gVGhpcyBtYXAgd2FzIGFkZGVkIGFzIGFuIGV4cGxvcmF0b3J5IHZpc3VhbCB0byBnZXQgYSBicm9hZCBzZW5zZSBvZiBob3cgc2hvcHBpbmcgYWN0aXZpdHkgdmFyaWVzIGFjcm9zcyB0aGUgY291bnRyeS4gVGhlIGRhcmtlciBwaW5rIHNoYWRlcyBzaG93IGhpZ2hlciBwdXJjaGFzZSB2b2x1bWUsIHdoaWNoIG1ha2VzIHN0YXRlcyBsaWtlIE1vbnRhbmEsIENhbGlmb3JuaWEsIGFuZCBJbGxpbm9pcyBzdGFuZCBvdXQgYSBiaXQgbW9yZS4gRXZlbiB0aG91Z2ggdGhlIG1hcCBpcyBnZW5lcmFsIGFuZCBvbmx5IHNob3dzIHN0YXRlLWxldmVsIHRvdGFscywgaXQgc3RpbGwgZ2V0cyB0aGUgcG9pbnQgYWNyb3NzOiBtb3N0IHN0YXRlcyBoYXZlIHByZXR0eSBzdGVhZHksIG1vZGVyYXRlIHNob3BwaW5nIGxldmVscywgd2l0aCBqdXN0IGEgZmV3IHRoYXQgbGVhbiBoaWdoZXIuIEl0IHdhcyBtYWlubHkgaW5jbHVkZWQgdG8gZXhwbG9yZSBvdmVyYWxsIHBhdHRlcm5zLCBub3QgdG8gbWFrZSBleGFjdCBvciBwZXJmZWN0bHkgcHJlZGljdGl2ZSBnZW9ncmFwaGljIHJlc3VsdHMuCgojIyMgVG90YWwgU3BlbmRpbmcgYnkgU2Vhc29uIOKYgO+4jyDinYTvuI8g8J+MtyDwn42CCgpgYGB7cn0Kc2hvcHBpbmcgJT4lCiAgZ3JvdXBfYnkoU2Vhc29uKSAlPiUKICBzdW1tYXJpc2UodG90YWxfc3BlbmRpbmcgPSBzdW0oYFB1cmNoYXNlX0Ftb3VudF8oVVNEKWApKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBTZWFzb24sIHkgPSB0b3RhbF9zcGVuZGluZywgZmlsbCA9IFNlYXNvbikpICsKICBnZW9tX2NvbCgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjb3JhbCIsICJtYXJvb24yIiwgImdvbGQiLCAibGlnaHRibHVlIikpICsKICBsYWJzKHRpdGxlID0gIlRvdGFsIFNwZW5kaW5nIGJ5IFNlYXNvbiIsIHggPSAiU2Vhc29uIiwgeSA9ICJUb3RhbCBTcGVuZGluZyAoaW4gRG9sbGFycykiKSArIAogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDExKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBzaXplID0gMTApLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCmBgYAotIFRoaXMgY2hhcnQgc2hvd3MgaG93IHRvdGFsIHNwZW5kaW5nIGNoYW5nZXMgYWNyb3NzIHRoZSBzZWFzb25zLiBGYWxsIGhhcyB0aGUgaGlnaGVzdCBzcGVuZGluZyBvdmVyYWxsLCB3aGlsZSBTdW1tZXIgaGFzIHRoZSBsb3dlc3QuIFNwcmluZyBhbmQgV2ludGVyIGFyZSBpbiB0aGUgbWlkZGxlIGFuZCBhcmUgZmFpcmx5IGNsb3NlIHRvIGVhY2ggb3RoZXIsIGxlYW5pbmcgbW9yZSB0b3dhcmQgdGhlIGhpZ2hlciBsZXZlbHMgc2VlbiBpbiBGYWxsLiBBbGwgdG9nZXRoZXIsIGl0IGdpdmVzIGEgc2ltcGxlIGxvb2sgYXQgd2hlbiBzaG9wcGVycyB0ZW5kIHRvIHNwZW5kIHRoZSBtb3N0IGFuZCBsZWFzdCB0aHJvdWdob3V0IHRoZSB5ZWFyLgoKCiMjIyBUb3AgNSBDb2xvcnMgYnkgU2Vhc29uCgpgYGB7cn0KdG9wX2NvbG9yc19ieV9zZWFzb24gPC0gc2hvcHBpbmcgJT4lCiAgY291bnQoU2Vhc29uLCBDb2xvciwgbmFtZSA9ICJPY2N1cnJlbmNlcyIpICU+JQogIGdyb3VwX2J5KFNlYXNvbikgJT4lCiAgc2xpY2VfbWF4KG9yZGVyX2J5ID0gT2NjdXJyZW5jZXMsIG4gPSA1KQoKZ2dwbG90KHRvcF9jb2xvcnNfYnlfc2Vhc29uLCBhZXMoeCA9IENvbG9yLCB5ID0gT2NjdXJyZW5jZXMsIGZpbGwgPSBTZWFzb24pKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgZmFjZXRfd3JhcCh+U2Vhc29uLCBzY2FsZXMgPSAiZnJlZV94IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAiRmFsbCIgPSAiY29yYWwiLAogICAgIlNwcmluZyIgPSAibWFyb29uMiIsCiAgICAiU3VtbWVyIiA9ICJnb2xkIiwKICAgICJXaW50ZXIiID0gImxpZ2h0Ymx1ZSIKICApKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRvcCA1IENvbG9ycyBpbiBFYWNoIFNlYXNvbiIsCiAgICB4ID0gIkNvbG9yIiwKICAgIHkgPSAiT2NjdXJyZW5jZXMiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKwogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwgICAgICAgICAgICAgICAgICMgYXBwbHkgZm9udAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiLCBmYWNlID0gImJvbGQiLCBzaXplID0gMTQpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAicGxheWZhaXIiKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInBsYXlmYWlyIiwgYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gOSksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJwbGF5ZmFpciIsIGZhY2UgPSAiYm9sZCIpCiAgKQoKYGBgCi0gVGhpcyBjaGFydCBzaG93cyB0aGUgdG9wIGZpdmUgY29sb3JzIGluIGVhY2ggc2Vhc29uIGFuZCBnaXZlcyBhIHF1aWNrIGZlZWwgZm9yIGhvdyBzaG9wcGVyIHByZWZlcmVuY2VzIHNoaWZ0IHRocm91Z2hvdXQgdGhlIHllYXIuIEZhbGwgdGVuZHMgdG8gbGVhbiB3YXJtIHdpdGggc2hhZGVzIGxpa2UgTWFnZW50YSwgT2xpdmUsIGFuZCBPcmFuZ2UuIFNwcmluZyBzd2l0Y2hlcyBpbnRvIGJyaWdodGVyIGNvbG9ycyBzdWNoIGFzIFBpbmsgYW5kIFRlYWwuIFN1bW1lciBoYXMgbW9yZSBjb29sIHRvbmVzIGxpa2UgU2lsdmVyLCBUZWFsLCBhbmQgR3JlZW4sIHdoaWxlIFdpbnRlciBicmluZ3MgaW4gZGVlcGVyIGNvbG9ycyBsaWtlIEdyZWVuLCBQZWFjaCwgYW5kIE1hcm9vbi4gT3ZlcmFsbCwgdGhlIGNvbG9yIHRyZW5kcyBsaW5lIHVwIHdpdGggdGhlIGdlbmVyYWwgbW9vZCBvZiBlYWNoIHNlYXNvbiBhbmQgaGVscCBzaG93IGhvdyBzaG9wcGVyIHByZWZlcmVuY2VzIGNoYW5nZSB0aHJvdWdob3V0IHRoZSB5ZWFyLgoKCiMgUmVzdWx0cwotIEZvciB0aGlzIHByb2plY3QsIHRoZSBmb2N1cyB3YXMgb24gZXhwbG9yaW5nIHRoZSBkYXRhIHZpc3VhbGx5IHRvIGZpZ3VyZSBvdXQgaG93IHBlb3BsZSBzaG9wIGFuZCB3aGF0IHBhdHRlcm5zIHN0YW5kIG91dC4gRGVzY3JpcHRpdmUgc3RhdGlzdGljcyBhbmQgZ3JhcGhzIGluIGdncGxvdDIgd2VyZSB1c2VkIHRvIGJyZWFrIHRoaW5ncyBkb3duIGJ5IGdlbmRlciwgY2F0ZWdvcnksIHNlYXNvbiwgbG9jYXRpb24sIGV0Yy4gU2luY2UgdGhlIGRhdGFzZXQgd2FzIGFscmVhZHkgY2xlYW4sIHRoZXJlIHdhc24ndCBtdWNoIG5lZWQgdG8gZG8gZGF0YSB3cmFuZ2xpbmcsIGl0IHdhcyBtb3N0bHkgZ3JvdXBpbmcsIHN1bW1hcml6aW5nLCBhbmQgdmlzdWFsaXppbmcgd2hhdCB3YXMgYWxyZWFkeSB0aGVyZS4KCi0gVGhpcyBhcHByb2FjaCB3YXMgYmVzdCBiZWNhdXNlIGl0IGxldHMgdGhlIGRhdGEgc3BlYWsgZm9yIGl0c2VsZi4gVGhlIGJveHBsb3RzLCBiYXIgY2hhcnRzLCBhbmQgbWFwIG1hZGUgaXQgZWFzeSB0byBmaW5kIGRpZmZlcmVuY2VzIGJldHdlZW4gZ3JvdXBzIGFuZCBmaW5kIHRyZW5kcyB0aGF0IG1pZ2h0IG5vdCBiZSBvYnZpb3VzIHdoZW4gbG9va2luZyBhdCByYXcgbnVtYmVycy4gVGhlIGNvbG9yIGFuZCBzaGFwZSBkaWZmZXJlbmNlcyBpbiBlYWNoIGNoYXJ0IGFsc28gaGVscCBzaG93IGdyb3VwIHRyZW5kcy4gVGhlIGdvYWwgd2FzIHRvIHVuZGVyc3RhbmQgd2hv4oCZcyBzaG9wcGluZywgd2hhdCB0aGV54oCZcmUgYnV5aW5nLCBhbmQgd2hlbiBhbmQgd2hlcmUgaXTigJlzIGhhcHBlbmluZywgYW5kIHZpc3VhbHMgaGVscGVkIG1ha2UgdGhhdCBzdG9yeSBjbGVhci4gCgotIE92ZXJhbGwsIGl0IHdhcyBmb3VuZCB0aGF0IG1vc3QgcGVvcGxlIHNwZW5kIGluIGEgc3RlYWR5IG1pZHJhbmdlLCB3aXRoIGRpZ2l0YWwgcGF5bWVudHMgbGlrZSBjcmVkaXQgY2FyZHMgYW5kIFBheVBhbCBiZWluZyB0aGUgbW9zdCBjb21tb24gTWVuIG1hZGUgbW9yZSB0b3RhbCBwdXJjaGFzZXMsIGJ1dCB0aGF04oCZcyBtb3N0bHkgYmVjYXVzZSB0aGVyZSBhcmUgbW9yZSBtYWxlIHNob3BwZXJzIGluIHRoZSBkYXRhc2V0LiBPbiBhdmVyYWdlLCB3b21lbiBhY3R1YWxseSBzcGVuZCBzbGlnaHRseSBtb3JlIHBlciBwdXJjaGFzZS4gQ29sb3JzIGxpa2UgcGluaywgdGVhbCwgYW5kIHllbGxvdyBzdGFuZCBvdXQgYWNyb3NzIGJvdGggZ3JvdXBzLCBhbmQgc2Vhc29ucyBsaWtlIHNwcmluZyBhbmQgZmFsbCBzZWUgdGhlIG1vc3Qgc2hvcHBpbmcgYWN0aXZpdHkuIFN0YXRlcyBsaWtlIE1vbnRhbmEsIENhbGlmb3JuaWEsIGFuZCBJbGxpbm9pcyBjYW1lIG91dCBvbiB0b3AgZm9yIHRvdGFsIHB1cmNoYXNlIHZvbHVtZS4KCgoKIyBDb25jbHVzaW9ucwoKLSBUaGlzIHByb2plY3QgaGVscGVkIHBvaW50IG91dCBob3cgYWxsIHRoZXNlIHNob3BwaW5nIGhhYml0cyBjb25uZWN0LCBsaWtlIGhvdyBnZW5kZXIsIGxvY2F0aW9uLCBhbmQgc2Vhc29uIGNhbiBpbmZsdWVuY2Ugd2hhdCBwZW9wbGUgYnV5IGFuZCB3aGVuLiBPbmUgbGltaXRhdGlvbiBpcyB0aGF0IHRoZSBkYXRhc2V0IGxlYW5zIG1vcmUgbWFsZSwgd2hpY2ggYWZmZWN0cyB0b3RhbHMgYW5kIHByZWZlcmVuY2VzLCBzbyB0aGF04oCZcyBzb21ldGhpbmcgdG8gY29uc2lkZXIgd2hlbiBsb29raW5nIGF0IHRoZSByZXN1bHRzLiBJdCBhbHNvIGRvZXNu4oCZdCBpbmNsdWRlIGRldGFpbHMgbGlrZSBjdXN0b21lciBpbmNvbWUgb3Igc3RvcmUgdHlwZSwgd2hpY2ggd291bGTigJl2ZSBoZWxwZWQgdG8gdW5kZXJzdGFuZCB3aHkgcGVvcGxlIHNwZW5kIHRoZSB3YXkgdGhleSBkby4gQW5vdGhlciBsaW1pdGF0aW9uIGlzIHRoYXQgd2hpbGUgZGF0YSBjYW4gYmUgYW5hbHl6ZWQgYnkgc2Vhc29uLCBpdCB3b3VsZCBiZSBldmVuIG1vcmUgaGVscGZ1bCBpZiB0aGUgZGF0YSBpbmNsdWRlZCB0aGUgZXhhY3QgbW9udGhzLiBUaGF0IHdheSwgc3BlY2lmaWMgaG9saWRheXMgb3Igc2FsZSBwZXJpb2RzIHdvdWxkIGJlIHNob3duIGFuZCBjb3VsZCBiZSBhbmFseXplZCB0byBzZWUgaG93IG1vcmUgc3BlY2lmaWMgdGltaW5nIGltcGFjdHMgc2hvcHBpbmcgYmVoYXZpb3IuCgotIEV2ZW4gd2l0aCB0aG9zZSBsaW1pdHMsIHRoZSB0cmVuZHMgYXJlIHJlYWxseSB1c2VmdWwuIFRoZSByZXN1bHRzIHN1Z2dlc3QgdGhhdCBjb252ZW5pZW5jZS1iYXNlZCBwYXltZW50IG1ldGhvZHMgZG9taW5hdGUsIG1pZC1yYW5nZSBzcGVuZGluZyBpcyB0eXBpY2FsLCBhbmQgcHVyY2hhc2luZyBwYXR0ZXJucyBhcmUgZmFpcmx5IGNvbnNpc3RlbnQgYWNyb3NzIHNlYXNvbnMgYW5kIGdlb2dyYXBoeS4gVGhpcyBtYXkgaGVscCBidXNpbmVzc2VzIGlkZW50aWZ5IHdoaWNoIHByb2R1Y3RzIGFuZCBwYXltZW50IG1ldGhvZHMgYXBwZWFsIG1vc3QgdG8gb25saW5lIHNob3BwZXJzLgoKLSBJZiB0aGlzIHByb2plY3Qgd2VyZSB0byBiZSBjb250aW51ZWQsIG5leHQgc3RlcHMgY291bGQgaW5jbHVkZSBkaWdnaW5nIGludG8gaG93IGFnZSBhZmZlY3RzIHNwZW5kaW5nIG9yIHdoZXRoZXIgY2VydGFpbiBwcm9kdWN0IGNhdGVnb3JpZXMgYXJlIG1vcmUgcG9wdWxhciB3aXRoIGRpZmZlcmVudCBhZ2UgZ3JvdXBzLiBBbHNvLCBjb21wYXJpbmcgdGhpcyBkYXRhIHRvIHJlYWwtd29ybGQgc2FsZXMgaW5mbyBvciBzdGF0ZSBwb3B1bGF0aW9ucyB0byBzZWUgaG93IGFjY3VyYXRlIHRoZSB0cmVuZHMgYXJlLiAKLSBPdmVyYWxsLCB0aGlzIHByb2plY3QgY2FtZSB0b2dldGhlciB3ZWxsIGFuZCBzaG93cyBhIGNsZWFyIHN0b3J5IGFib3V0IHRoZSBjb25zdW1lcnMgaW4gdGhpcyBkYXRhc2V0LCB3aGF0IHRoZXkncmUgYnV5aW5nLCBhbmQgd2hlbiBhbmQgaG93IHRoZXkncmUgZG9pbmcgaXQuCgoKCiMgUmVmZXJlbmNlcwotIERhdGEgVmlzdWFsaXphdGlvbiB3aXRoIGdncGxvdDIgOiA6IENIRUFUIFNIRUVULiAtIChuLmQuKS4gUmV0cmlldmVkIE5vdmVtYmVyIDEwLCAyMDI1LCBmcm9tIGh0dHBzOi8vbGlsZS5kdWtlLmVkdS93cC1jb250ZW50L3VwbG9hZHMvMjAyMC8wNy9SX2dncGxvdDJfY2hlYXRzaGVldC5wZGYKLSBHb29nbGUgRm9udHMuIChuLmQuKS4gR29vZ2xlIEZvbnRzLiBodHRwczovL2ZvbnRzLmdvb2dsZS5jb20vc3BlY2ltZW4vUGxheWZhaXIrRGlzcGxheQotIEhhZGxleSBXaWNraGFtLiAoMjAxOSkuIGdncGxvdDI6IEVsZWdhbnQgR3JhcGhpY3MgZm9yIERhdGEgQW5hbHlzaXMuCi0gR2dwbG90Mi1Cb29rLm9yZy4gaHR0cHM6Ly9nZ3Bsb3QyLWJvb2sub3JnL0xvcmVuem8sIFAuIEQuICgyMDI1KS4gCi0gVVMgTWFwcyBJbmNsdWRpbmcgQWxhc2thIGFuZCBIYXdhaWkgW1IgcGFja2FnZSB1c21hcCB2ZXJzaW9uIDEuMC4wXS4gUi1Qcm9qZWN0Lm9yZy4gaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvcGFja2FnZT11c21hcFBhY2thZ2UgLSDigJxnZ3Bsb3Qy4oCdIFRpdGxlIENyZWF0ZSBFbGVnYW50IERhdGEgVmlzdWFsaXNhdGlvbnMgVXNpbmcgdGhlIEdyYW1tYXIgb2YgR3JhcGhpY3MuICgyMDIwKS4gaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dncGxvdDIvZ2dwbG90Mi5wZGYgCi0gUiBmb3IgRGF0YSBTY2llbmNlICgyZSkuIChuLmQuKS4gUjRkcy5oYWRsZXkubnouIGh0dHBzOi8vcjRkcy5oYWRsZXkubnovCi0gWnViYWlyYSBNYWltb25hLiAoMjAyNSkuIFNob3BwaW5nIGJlaGF2aW91cnMgZGF0YXNldC4gS2FnZ2xlLmNvbS4gaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy96dWJhaXJhbXV0aS9zaG9wcGluZy1iZWhhdmlvdXJzLWRhdGFzZXQvZGF0YQ==